package com.rp.goouploader;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;

import com.rp.common.utils.PropertiesLoader;
import com.rp.common.utils.RpUtil;
import com.rp.upload.service.AttachmentService;

public class GoouploadFileServlet extends HttpServlet implements Servlet {

	private static final long serialVersionUID = 9110563080306845122L;
	
	//缓冲内存
	public static final int BUFF_FILE_MAXSIZE = 1 * 1024 * 1024;
	//限制上传的总文件大小：3G
	public static final long FILE_MAXSIZE = 3221225472L;
	
	
	//保存上传文件的目录路径
	protected String saveDirPath = null;
	//保存上传文件的目录
	protected File saveDir = null;
	//如果要获取前端传回的参数，可以通过form.getValue(key)的方式获取
	protected GooForm form = null;
	//标记是否将上传文件存入数据库
	protected String saveToDb = "true";
	//标记是否对上传的文件进行重命名
	protected String fileRename = "true";
	//标记是否需要执行自定义操作
	protected String customOperaImpl = "0";
	//RP平台附件服务类
	protected AttachmentService attachmentService;
	
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doPost(request, response);
	}
	
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		//System.out.println("开始Goo文件上传");
		
		DiskFileItemFactory factory = new DiskFileItemFactory();
		factory.setSizeThreshold(BUFF_FILE_MAXSIZE);
		
		ServletFileUpload fileUpload = new ServletFileUpload(factory);
		fileUpload.setHeaderEncoding("UTF-8");
		fileUpload.setSizeMax(FILE_MAXSIZE);
		
		//文件保存在服务器的绝对路径
		String saveAbsolutePath = "";
		
		try {
			List<FileItem> fileList = fileUpload.parseRequest(request);
			
			HashMap<String, Object> map = new HashMap<String, Object>();
			for(FileItem fileItem : fileList) {
				//处理表单域中其他不是文件域的信息
				if (fileItem.isFormField()) {
	   		   		String fieldSubName = fileItem.getFieldName();
	   		   		//swfupload用 utf-8
	   		   	   	map.put(fieldSubName, new String(fileItem.getString("UTF-8")));	
				}
			}
			
			form = new GooForm();
			form.setMapData(map);
			
			String entityName = form.getValue("entityName"); 
			String entityId = form.getValue("entityId");
			
			String webSaveDirPath = form.getValue("webSaveDirPath");
			//如果saveDirPath由前台传入，则修改默认的saveDirPath配置
			if(!webSaveDirPath.equals("0")){
				this.saveDirPath = webSaveDirPath;
			}else{
				this.saveDirPath = PropertiesLoader.getValue("goouploadSaveDirPath", "upload-config.properties");
			}
			this.saveDir = new File(saveDirPath);
			if (!this.saveDir.isDirectory())
				this.saveDir.mkdir();
			
			saveToDb = form.getValue("saveToDb");
			fileRename = form.getValue("fileRename");
			customOperaImpl = form.getValue("customOperaImpl");
			
			//处理上传文件，将其保存入磁盘或将文件信息存入数据库
			for (FileItem fileItem : fileList) {
				
				if(!fileItem.isFormField()){
					//文件名
					String fileName = URLDecoder.decode(fileItem.getName(), "UTF-8");
					//文件大小
					long fileSize = fileItem.getSize();
					//文件类型
					String fileType = RpUtil.cutFileSuffixName(fileItem.getName());
					
					////////////////////磁盘操作 开始////////////////////
					
					if((fileName == null || fileName.equals("")) 
							&& fileSize == 0)
	    	   			continue;
					
					//生成新的文件名称，默认生成规则为GUID+当前日期，可以根据需要自定义
					String newFileName = RpUtil.createGuid() + "_" 
							+ RpUtil.getTodayDate(null) + RpUtil.cutFileSuffixName(fileName);
					
					//拼装文件保存在服务器的绝对路径
					if(fileRename.equals("true")){
						saveAbsolutePath = saveDirPath + newFileName;
					}else{
						saveAbsolutePath = saveDirPath + fileName;
					}
					
					File file = new File(saveAbsolutePath);
					fileItem.write(file);
					fileItem.delete();
					
					////////////////////磁盘操作 结束////////////////////
					
					
					////////////////////数据库操作 开始////////////////////
					
					if(saveToDb.equals("true")){
						//将上传的文件信息存入数据库的附件表。
						//2014年10月10日注：此操作其实可以移至自定义操作中进行，
						attachmentService.addAttachment(
								fileName, 
								newFileName,
								"",
								RpUtil.convertFileSize(fileSize),
								fileType,
								saveAbsolutePath,
								entityName, entityId);
					}
					
					////////////////////数据库操作 结束////////////////////
					
					////////////////////自定义操作///////////////////////
					if(!customOperaImpl.equals("0")){
						GooFileInfo fi = new GooFileInfo();
						fi.setFileName(fileName);
						fi.setNewFileName(newFileName);
						fi.setFileType(fileType);
						fi.setSaveAbsolutePath(saveAbsolutePath);
						try{
							CustomOpera co = (CustomOpera) RpUtil.getBean(customOperaImpl);
							co.customOpera(fi, form, fileItem);
						}catch (Exception e) {
							e.printStackTrace();
							System.out.println("来自GoouploadFileServlet的消息：自定义操作执行失败！");
						}
						
					}
					////////////////////自定义操作 结束///////////////////////
					
				}
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			//如果过程中发生异常，则将存入磁盘中的文件删除
			RpUtil.deleteFile(saveAbsolutePath);
			//返回错误信息，此段代码的作用是让前端插件可以检测出后台处理的结果，显示上传失败的提示
			response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "服务器端出错，错误代码：500");
		} finally {
			saveAbsolutePath = "";
		}
		
	}

	public void init() throws ServletException {
		super.init();
		
		String[] configLocations = {"/WEB-INF/applicationContext.xml"};
		ConfigurableWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
		webApplicationContext.setServletContext(this.getServletContext());
		webApplicationContext.setConfigLocations(configLocations);
		webApplicationContext.refresh();
		//实例化AttachmentService
		attachmentService = (AttachmentService) webApplicationContext.getBean("attachmentService");
		
		System.out.println("GoouploadFileServlet Init");
	}
	
}

